#include "for_range.h"

// 我们实现python中的 'for i in range(start, end, step)'
template<typename value_t>
class range_impl {
    class range_iterator;
public:
    range_impl(value_t begin, value_t end, value_t step = 1) 
        : m_begin(begin), m_end(end), m_step(step) {
        if (step > 0 && m_begin >= m_end)
            throw std::logic_error("end must greater than begin.");
        else if (step < 0 && m_begin <= m_end)
            throw std::logic_error("end must less than begin.");

        m_step_end = (m_end - m_begin) / m_step;
        if (m_begin + m_step_end*m_step != m_end) {
            m_step_end++;
        }
    }

    range_iterator begin() {
        return range_iterator(0, *this);
    }

    range_iterator end() {
        return range_iterator(m_step_end, *this);
    }

    value_t operator[](int s) {
        return m_begin + s*m_step;
    }

    int size() {
        return m_step_end;
    }

private:
    value_t m_begin;
    value_t m_end;
    value_t m_step;
    int m_step_end;

    class range_iterator {
    public:
        range_iterator(int start, range_impl& range) 
            : m_current_step(start), m_range(range) {
            m_current_value = m_range.m_begin + m_current_step*m_range.m_step;
        }

        value_t operator*() { return m_current_value; }

        const range_iterator* operator++() {
            m_current_value += m_range.m_step;
            m_current_step++;
            return this;
        }

        bool operator==(const range_iterator& other) {
            return m_current_step == other.m_current_step;
        }

        bool operator!=(const range_iterator& other) {
            return m_current_step != other.m_current_step;
        }

        const range_iterator* operator--() {
            m_current_value -= m_range.m_step;
            m_current_step--;
            return this;
        }

    private:
        value_t m_current_value;
        int m_current_step;
        range_impl& m_range;
    };
};

template<typename T, typename V>
auto range(T begin, T end, V stepsize)->range_impl<decltype(begin + end + stepsize)> {
    return range_impl<decltype(begin + end + stepsize)>(begin, end, stepsize);
}

template<typename T>
range_impl<T> range(T begin, T end) {
    return range_impl<T>(begin, end, 1);
}

template<typename T>
range_impl<T> range(T end) {
    return range_impl<T>(T(), end, 1);
}



int for_range(void) {
    std::vector<int> vec;
    std::map<std::string, int> mm;
    // C++ 98/03
    for (std::vector<int>::iterator i = vec.begin(); i != vec.end(); ++i) {
        // code here
    }

    // C++11 v1
    for (auto i = vec.begin(); i != vec.end(); ++i) {
        // code here
    }

    // C++11 v2
    for(auto& val : vec) {
        // code here
    }

    for(auto& val : mm) {
        // code here
        std::cout << val.first << " " << val.second << std::endl;
    }


    for (auto  val : range(50)) {
        std::cout << val << " ";
    } 
    std::cout << std::endl;
    std::cout << "\033[32mThis text is green!\033[0m\n" << std::endl;


    return 0;
}